home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
src
/
demos
/
GL
/
bounce
/
bounce.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
14KB
|
773 lines
/*
* Copyright (C) 1991, Silicon Graphics, Inc.
* All Rights Reserved.
*/
/**************************************************************************
* *
* Copyright (C) 1988, 1989, 1990, Silicon Graphics, Inc. *
* *
* These coded instructions, statements, and computer programs contain *
* unpublished proprietary information of Silicon Graphics, Inc., and *
* are protected by Federal copyright law. They may not be disclosed *
* to third parties or copied or duplicated in any form, in whole or *
* in part, without the prior written consent of Silicon Graphics, Inc. *
* *
**************************************************************************/
/*
* foo $Revision: 1.16 $
*/
#include "math.h"
#include "stdio.h"
#include "gl.h"
#include "device.h"
#define UDIV 12
#define VDIV 12
#define WALLGRID 8
#define EYEZ 3.3
#define TOTALBALLS 3
#define R 0
#define G 1
#define B 2
#define X 0
#define Y 1
#define Z 2
#define W 3
int freeze = FALSE;
int spin = FALSE;
int objecton = FALSE;
int normson = FALSE;
int lighton[3] = {TRUE, TRUE, TRUE};
struct {
float p[3];
float d[3];
int color[3];
} balls[TOTALBALLS];
float ballobj[UDIV+1][VDIV+1][4];
float wallobj[WALLGRID+1][WALLGRID+1][4];
float wallnorms[WALLGRID+1][WALLGRID+1][3];
float wallnorm[3] = { 0.0, 0.0, -1.0 };
int rx, ry;
int orx, ory;
float ballscale;
float ballsize;
long xsize, ysize;
int menu = 0;
int lflag = 0;
char machinetype[12];
static enum {
MACH_G,
MACH_GT,
MACH_VGX,
MACH_PI
} machine;
float rotm[3][3],rotmi[3][3],curmat[3][3];
float light1[] = {
AMBIENT, 0.0, 0.0, 0.0,
LCOLOR, 1.0, 0.1, 0.1,
POSITION, 0.0, 0.0, 0.0, 1.0,
LMNULL };
float light2[] = {
AMBIENT, 0.0, 0.0, 0.0,
LCOLOR, 0.1, 1.0, 0.1,
POSITION, 0.0, 0.0, 0.0, 1.0,
LMNULL };
float light3[] = {
AMBIENT, 0.0, 0.0, 0.0,
LCOLOR, 0.1, 0.1, 1.0,
POSITION, 0.0, 0.0, 0.0, 1.0,
LMNULL };
float newpos[] = {
POSITION, 0.0, 0.0, 0.0, 1.0,
LMNULL };
float planemat[] = {
EMISSION, 0.0, 0.0, 0.0,
AMBIENT, 0.0, 0.0, 0.0,
DIFFUSE, 0.4, 0.4, 0.4,
SPECULAR, 1.0, 1.0, 1.0,
SHININESS, 30.0,
LMNULL };
float wallmat[] = {
EMISSION, 0.0, 0.0, 0.0,
AMBIENT, 0.1, 0.1, 0.1,
DIFFUSE, 0.8, 0.8, 0.8,
SPECULAR, 1.0, 1.0, 1.0,
SHININESS, 20.0,
LMNULL };
float lmodel[] = {
AMBIENT,0.3,0.3,0.3,
LOCALVIEWER,1.0,
ATTENUATION, 1.0, 3.0,
LMNULL };
extern float frand();
char ofile[80];
/************************************************************/
/* XXX - The following is an excerpt from spin.h from spin */
/************************************************************/
#define POLYGON 1
#define LINES 2
#define TRANSPERENT 3
#define DISPLAY 4
#define LMATERIAL 5
#define FASTMAGIC 0x5423
typedef struct fastobj {
int npoints;
int colors;
int type;
int material;
int display;
int ablend;
int *data;
} fastobj;
fastobj *readfastobj();
/*
* Wrappers to do either lines or polygons
*/
#define PolyOrLine() if (lflag == LINES) { \
bgnclosedline(); \
} else if (POLYGON) { \
bgnpolygon(); \
}
#define EndPolyOrLine() if (lflag == LINES) { \
endclosedline(); \
} else if (POLYGON) { \
endpolygon(); \
}
/************************* end of spin.h excerpt *************************/
fastobj *obj = NULL;
main(argc, argv)
int argc;
char **argv;
{
if (argc > 1)
{
int i;
for (i=0; argv[1][i] != '/' && argv[1][i] != '\0'; i++);
if (argv[1][i] != '/')
{
strcpy(ofile, "/usr/demos/data/models/");
strcat(ofile, argv[1]);
}
else
strcpy(ofile, argv[1]);
if (obj = readfastobj(ofile))
objecton = TRUE;
}
ballsize = .04;
ballscale = 1.0 - ballsize;
initialize(argv);
make_menu();
resetballs();
getsize(&xsize, &ysize);
mmode(MVIEWING);
perspective(600, (float)xsize/ysize, EYEZ-2.0, EYEZ+2.0);
translate(0.0, 0.0, -EYEZ);
/* Use local lights for the box */
lmbind(LIGHT0, 1);
lmbind(LIGHT1, 2);
lmbind(LIGHT2, 3);
while(1) {
calcbox();
if (!freeze)
calcball();
drawimage();
}
}
resetballs()
{
register short i;
balls[0].color[R] = 255;
balls[0].color[G] = 64;
balls[0].color[B] = 64;
balls[1].color[R] = 64;
balls[1].color[G] = 255;
balls[1].color[B] = 64;
balls[2].color[R] = 64;
balls[2].color[G] = 64;
balls[2].color[B] = 255;
for (i = 0; i < TOTALBALLS; i++) {
balls[i].p[0] = 0.0;
balls[i].p[1] = 0.0;
balls[i].p[2] = 0.0;
balls[i].d[0] = .1*frand();
balls[i].d[1] = .1*frand();
balls[i].d[2] = .1*frand();
}
}
drawimage()
{
register short i;
check_q();
zbuffer(FALSE);
if (machine == MACH_GT) {
czclear(0, 0); /* Simultaneously clear z and color buffers */
} else {
/* czclear(0, 0x7fffff); */
czclear(0, getgdesc(GD_ZMAX));
}
lmbind(LMODEL, 1);
pushmatrix();
rotate(ry, 'y' );
rotate(rx, 'x' );
for (i=0; i < TOTALBALLS; i++) {
newpos[1] = balls[i].p[0];
newpos[2] = balls[i].p[1];
newpos[3] = balls[i].p[2];
lmdef( DEFLIGHT, i+1, 6, newpos );
}
lmbind(MATERIAL, 1);
drawbox();
zbuffer(TRUE);
if (objecton)
{
lmbind(MATERIAL, 2);
pushmatrix();
scale(1.5, 1.5, 1.5);
rotate(1800, 'z');
if (spin)
{
orx += 50;
ory += 50;
}
rotate(orx, 'x');
rotate(ory, 'y');
drawfastobj(obj);
popmatrix();
}
lmbind(LMODEL, 0);
for (i=0; i < TOTALBALLS; i++) {
if (lighton[i])
{
pushmatrix();
translate( balls[i].p[0],balls[i].p[1],balls[i].p[2] );
c3i(balls[i].color);
drawball();
popmatrix();
}
}
popmatrix();
swapbuffers();
}
initialize(argv)
char **argv;
{
long time();
{ /* Open window with name of executable */
char *t, *strrchr();
winopen((t=strrchr(argv[0], '/')) != NULL ? t+1 : argv[0]);
}
if (getgdesc(GD_BITS_NORM_SNG_RED) < 3)
{
system("inform 'Your system must support RGB mode to run bounce'");
exit(1);
}
if (getgdesc(GD_BITS_NORM_ZBUFFER) == 0)
{
system("inform 'Your system must have a z-buffer to run bounce'");
exit(1);
}
doublebuffer();
RGBmode();
gconfig();
gversion(machinetype);
if (strncmp (machinetype,"GL4DPI", strlen("GL4DPI")) == 0)
machine = MACH_PI;
else if (strncmp (machinetype, "GL4DGT", strlen("GL4DGT")) == 0)
machine = MACH_GT;
else if (strncmp (machinetype, "GL4DVGX", strlen("GL4DVGX")) == 0)
machine = MACH_VGX;
else machine = MACH_G;
/* Setup to use simultaneous z and color buffer clear */
switch(machine)
{
case MACH_GT:
zfunction(ZF_GEQUAL);
lsetdepth(0x7fffff, 0x0ff);
break;
case MACH_PI:
case MACH_G:
case MACH_VGX:
default:
/*
* use default z setup
*/
break;
}
initobjects();
srand((unsigned)time(0));
lmdef(DEFLMODEL, 1, 10, lmodel);
lmdef(DEFMATERIAL, 1, 19, wallmat);
lmdef(DEFMATERIAL, 2, 19, planemat);
lmdef(DEFLIGHT, 1, 14, light1);
lmdef(DEFLIGHT, 2, 14, light2);
lmdef(DEFLIGHT, 3, 14, light3);
qdevice(RIGHTMOUSE);
qdevice(MIDDLEMOUSE);
qdevice(LEFTMOUSE);
qdevice(ESCKEY);
}
initobjects()
{
register float u,v,du,dv;
register short i,j;
du = 2.0*3.1416/UDIV;
dv = 3.1416/VDIV;
u = 0.;
for (i=0; i <= UDIV; i++) {
v = 0.;
for (j=0; j <= VDIV; j++) {
ballobj[i][j][X] = ballsize*cos(u)*sin(v);
ballobj[i][j][Y] = ballsize*sin(u)*sin(v);
ballobj[i][j][Z] = ballsize*cos(v);
ballobj[i][j][W] = 1.0;
v += dv;
}
u += du;
}
for (i=0; i <= WALLGRID; i++) {
for (j=0; j <= WALLGRID; j++) {
wallobj[i][j][X] = -1.0 + 2.0*i/WALLGRID;
wallobj[i][j][Y] = -1.0 + 2.0*j/WALLGRID;
wallobj[i][j][Z] = 1.0;
wallobj[i][j][W] = 1.0;
}
}
for (i=0; i <= WALLGRID; i++) {
for (j=0; j <= WALLGRID; j++) {
wallnorms[i][j][X] = wallobj[i][j][X] + wallnorm[X]*0.1;
wallnorms[i][j][Y] = wallobj[i][j][Y] + wallnorm[Y]*0.1;
wallnorms[i][j][Z] = wallobj[i][j][Z] + wallnorm[Z]*0.1;
}
}
}
drawball()
{
register int i,j;
for (i=0; i < UDIV; i++) {
for (j=0; j < VDIV; j++) {
bgnpolygon();
v4f( ballobj[i][j] );
v4f( ballobj[i+1][j] );
v4f( ballobj[i+1][j+1] );
v4f( ballobj[i][j+1] );
endpolygon();
}
}
}
drawface()
{
register int i,j;
n3f(wallnorm);
for (i=0; i < WALLGRID; i++) {
bgntmesh();
for (j=0; j <= WALLGRID; j++) {
v3f(wallobj[i][j]);
v3f(wallobj[i+1][j]);
}
endtmesh();
}
}
drawnorms()
{
register int i,j;
lmbind(LMODEL, 0);
RGBcolor(255, 0, 255);
for (i=0; i <= WALLGRID; i++) {
for (j=0; j <= WALLGRID; j++) {
bgnline();
v3f(wallobj[i][j]);
v3f(wallnorms[i][j]);
endline();
}
}
lmbind(LMODEL, 1);
}
drawbox()
{
pushmatrix();
/* drawface(); */
rotate(900, 'y');
drawface();
if (normson) drawnorms();
rotate(900, 'y');
drawface();
if (normson) drawnorms();
rotate(900, 'y');
/* drawface(); */
rotate(-900, 'x');
drawface();
if (normson) drawnorms();
rotate(1800, 'x');
/* drawface(); */
popmatrix();
}
calcbox()
{
rx = -800*getvaluator(MOUSEY)/getgdesc(GD_YPMAX) - 50;
ry = 50 + 800*getvaluator(MOUSEX)/getgdesc(GD_XPMAX);
}
calcball()
{
register short i,j;
for (j=0; j < TOTALBALLS; j++) {
for (i=0; i < 3; i++) {
balls[j].p[i] += balls[j].d[i];
if (fabs(balls[j].p[i]) > ballscale) {
balls[j].p[i] = (balls[j].p[i] > 0.0) ?
ballscale : -ballscale;
balls[j].d[i] = -balls[j].d[i];
}
}
}
}
float frand()
{
return 2.0*(rand()/32768.0 - .5);
}
check_q()
{
short val;
while(qtest())
{
switch(qread(&val))
{
case REDRAW:
reshapeviewport();
break;
case ESCKEY:
if (!val)
{
gexit();
exit(0);
}
break;
case MENUBUTTON:
if (val)
switch(dopup(menu)) {
case 1:
if (lighton[0] = !lighton[0])
lmbind(LIGHT0, 1);
else
lmbind(LIGHT0, 0);
break;
case 2:
if (lighton[1] = !lighton[1])
lmbind(LIGHT1, 2);
else
lmbind(LIGHT1, 0);
break;
case 3:
if (lighton[2] = !lighton[2])
lmbind(LIGHT2, 3);
else
lmbind(LIGHT2, 0);
break;
case 4:
freeze = !freeze;
break;
case 5:
if (obj)
objecton = !objecton;
else
exit();
break;
case 6:
spin = !spin;
break;
case 7:
exit();
break;
}
make_menu();
break;
default:
break;
}
}
}
make_menu()
{
char buf[256];
if (menu)
freepup(menu);
strcpy(buf, "bounce %t");
if (lighton[0])
strcat(buf, "|red light off");
else
strcat(buf, "|red light on");
if (lighton[1])
strcat(buf, "|green light off");
else
strcat(buf, "|green light on");
if (lighton[2])
strcat(buf, "|blue light off");
else
strcat(buf, "|blue light on");
if (freeze)
strcat(buf, "|unfreeze lights");
else
strcat(buf, "|freeze lights");
if (obj)
{
if (objecton)
strcat(buf, "|object off");
else
strcat(buf, "|object on");
if (spin)
strcat(buf, "|object spin off");
else
strcat(buf, "|object spin on");
}
strcat(buf, "|exit");
menu = defpup(buf);
}
/**********************************************************/
/* XXX - The following is a clone of fastobj.c from spin */
/**********************************************************/
fastobj *readfastobj(name)
char *name;
{
FILE *inf;
fastobj *obj;
int i;
int nlongs;
int magic;
int *ip;
char filename[512];
inf = fopen(name,"r");
if(!inf) {
sprintf(filename,"%s",name);
inf = fopen(filename,"r");
if(!inf) {
fprintf(stderr,"readfast: can't open input file %s\n",name);
exit(1);
}
}
fread(&magic,sizeof(int),1,inf);
if(magic != FASTMAGIC) {
fprintf(stderr,"readfast: bad magic in object file\n");
fclose(inf);
exit(1);
}
obj = (fastobj *)malloc(sizeof(fastobj));
fread(&obj->npoints,sizeof(int),1,inf);
fread(&obj->colors,sizeof(int),1,inf);
/*
* Insure that the data is quad-word aligned and begins on a page
* boundary. This shields us from the performance loss which occurs
* whenever we try to fetch data which straddles a page boundary (the OS
* has to map in the next virtual page and re-start the DMA transfer).
*/
nlongs = 8 * obj->npoints;
obj->data = (int *) malloc(nlongs*sizeof(int) + 4096);
obj->data = (int *) (((int)(obj->data)) + 0xfff);
obj->data = (int *) (((int)(obj->data)) & 0xfffff000);
for (i = 0, ip = obj->data; i < nlongs/4; i++, ip += 4)
fread(ip, 3 * sizeof(int), 1, inf);
fclose(inf);
return obj;
}
drawfastobj(obj)
fastobj *obj;
{
register int *p, *end;
register int npolys;
p = obj->data;
end = p + 8 * obj->npoints;
if(obj->colors) {
npolys = obj->npoints/4;
p = obj->data;
while(npolys--) {
PolyOrLine();
c3i(p);
v3f((float *)p+4);
c3i(p+8);
v3f((float *)p+12);
c3i(p+16);
v3f((float *)p+20);
c3i(p+24);
v3f((float *)p+28);
EndPolyOrLine();
p += 32;
}
} else {
while ( p < end) {
PolyOrLine();
n3f((float *)p);
v3f((float *)p+4);
n3f((float *)p+8);
v3f((float *)p+12);
n3f((float *)p+16);
v3f((float *)p+20);
n3f((float *)p+24);
v3f((float *)p+28);
EndPolyOrLine();
p += 32;
}
}
}
/*
* objmaxpoint
*
* find the vertex farthest from the origin,
* so we can set the near and far clipping planes tightly.
*/
#define MAXVERT(v) if ( (len = sqrt( (*(v)) * (*(v)) + \
(*(v+1)) * (*(v+1)) + \
(*(v+2)) * (*(v+2)) )) > max) \
max = len;
float
objmaxpoint(obj)
fastobj *obj;
{
register float *p, *end;
register int npolys;
register float len;
register float max = 0.0;
p = (float *) (obj->data);
if (obj->colors) {
npolys = obj->npoints/4;
while(npolys--) {
MAXVERT(p+4);
MAXVERT(p+12);
MAXVERT(p+20);
MAXVERT(p+28);
p += 32;
}
} else {
end = p + 8 * obj->npoints;
while ( p < end) {
MAXVERT(p+4);
MAXVERT(p+12);
MAXVERT(p+20);
MAXVERT(p+28);
p += 32;
}
}
return max;
}